
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Text.RegularExpressions;
using System.Xml;

namespace Swaf.Container
{
	/// <summary>
	/// RuleCatalogContainerNode provides a general purpose catalog type which uses a 
	/// business rule to instantiate the requested entry type.  This catalog can be used
	/// to wrap multiple catalog types and provide failover type support (look on file system,
	/// then in db) or to add versioning or custom biz logic to the catalog entry creation.
	/// 
	/// The RuleCatalogContainerNode is instantiated using the following config pattern:
	/// catalog using rule {rule name}
	/// 
	/// The parameters passed into the Get/Put are passed on to the rule call along with the catalog name and the method (get/put)
	///	in a single INameAddressSupport instance (Dictionary).
	/// </summary>
	public class RuleCatalogContainerNode : INameAddressSupport, IMap, ICatalog
	{
		protected FlexiMap m_map;
		protected bool m_usingSpecifiedClassFactory;
		protected string m_catalogName=null;
		protected string m_cacheType=null;
		protected string m_ruleName=null;
		public string catalogName
		{
			get
			{
				return m_catalogName;
			}
			set
			{
				m_catalogName=value;
			}
		}

		public XmlElement getCatalogContents(string fullName)
		{
			//TODO: Someday, try to implement this if actually needed.
			return null;
		}

		public RuleCatalogContainerNode(Match mr, object[] extraInfo)
		{
			if(mr.Groups.Count == 1 || mr.Groups.Count == 2) 
			{
				m_ruleName = mr.Groups[1].Value;

				m_map = new FlexiMap();

				if(mr.Groups.Count == 2)
					m_cacheType = mr.Groups[2].Value;
			}
		}
		#region INameAddressSupport Members

		public bool containsField(string nameAddress)
		{
			return false;
		}

		public bool isGetOnly
		{
			get
			{
				return false;
			}
		}

		public Swaf.Container.XmlSerializationSupport SerializationSupport
		{
			get
			{
				return Swaf.Container.XmlSerializationSupport.None;
			}
		}

		public void put(string nameAddress, object val, object extraInfo)
		{
			INameAddressSupport map = new FlexiMap();
			map.put("catalog", m_catalogName);
			map.put("method", "put");
			map.put("key", nameAddress);
			map.put("params", val);
			map.put("extraInfo", extraInfo);
			IResults results = Application.currentApp.ruleMgr.execute(m_ruleName,map);
			if (results.ExceptionInfo != null)
			{
				throw new Swaf.Container.CatalogException(string.Format("Exception getting value from catalog {0} using rule {1}.",m_catalogName,m_ruleName), results.ExceptionInfo);
			}
		}

		void Swaf.Container.INameAddressSupport.put(string nameAddress, object val)
		{
			put(nameAddress,val, null);
		}

		public string getXml(string options)
		{
			return null;
		}

		public object get(string nameAddress)
		{
			return internalGet(nameAddress, null);
		}
		private object internalGet(string nameAddress, object args)
		{
			INameAddressSupport map = new FlexiMap();
			map.put("catalog", m_catalogName);
			map.put("method", "get");
			map.put("key", nameAddress);
			map.put("params", args);
			map.put("extraInfo", null);
			IResults results = Application.currentApp.ruleMgr.execute(m_ruleName,map);
			if (results.ExceptionInfo != null)
			{
				throw new Swaf.Container.CatalogException(string.Format("Exception getting value from catalog {0} using rule {1}.",m_catalogName,m_ruleName), results.ExceptionInfo);
			}
			return results.CallResults;
		}

		object Swaf.Container.INameAddressSupport.get(string nameAddress, object oneArg)
		{
			return internalGet(nameAddress, oneArg);
		}
		object Swaf.Container.INameAddressSupport.get(string nameAddress, params object[] infoArgs)
		{
			return internalGet(nameAddress, infoArgs);
		}

		public string Xml
		{
			get
			{
				return null;
			}
		}

		#endregion

		#region IDictionary Members

		public bool IsReadOnly
		{
			get
			{
				return false;
			}
		}

		public System.Collections.IDictionaryEnumerator GetEnumerator()
		{
			return null;
		}

		public object this[object key]
		{
			get
			{
				return get((string) key);
			}
			set
			{
				put((string) key, value, null);
			}
		}

		public void Remove(object key)
		{
			// Nothing to do.
		}

		public bool Contains(object key)
		{
			return false;
		}

		public void Clear()
		{
			// Nothing to do.
		}

		public System.Collections.ICollection Values
		{
			get
			{
				return null;
			}
		}

		public void Add(object key, object value)
		{
			put((string) key, value, null);
		}

		public System.Collections.ICollection Keys
		{
			get
			{
				return null;
			}
		}

		public bool IsFixedSize
		{
			get
			{
				return false;
			}
		}

		#endregion

		#region ICollection Members

		public bool IsSynchronized
		{
			get
			{
				return false;
			}
		}

		public int Count
		{
			get
			{
				return 0;
			}
		}

		public void CopyTo(Array array, int index)
		{
		}

		public object SyncRoot
		{
			get
			{
				return null;
			}
		}

		#endregion

		#region IEnumerable Members

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
			return null;
		}

		#endregion
	}
}
